package com.sd.repay.service.impl;

import com.sd.repay.common.Constants;
import com.sd.repay.dao.BaseDao;
import com.sd.repay.pojo.WithdrawOrder;
import com.sd.repay.service.WithdrawOrderService;
import com.sd.repay.utils.DateUtil;
import com.sd.repay.utils.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author sd
 * @Description: 统一出账服务类
 * @date 2017年10月25日
 */
@Service
public class WithdrawOrderServiceImpl implements WithdrawOrderService {

    private static Logger log = LoggerFactory.getLogger(WithdrawOrderServiceImpl.class);

    @Autowired
    private BaseDao baseDao;


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public int saveWithdrawOrder(WithdrawOrder withdrawOrder) throws Exception {
        String sql = " INSERT INTO t_withdraw_order(order_no, mer_type, mer_no, service, service_order_no, acq_code, card_no, " +
                " account_no, account_name, amount, fee, create_time)" +
                " VALUES(?,?,?,?,?,?,?,?,?,?,?,?) ";
        List<Object> params = new ArrayList<>();
        params.add(withdrawOrder.getOrderNo());
        params.add(withdrawOrder.getMerType());
        params.add(withdrawOrder.getMerNo());
        params.add(withdrawOrder.getService());
        params.add(withdrawOrder.getServiceOrderNo());
        params.add(withdrawOrder.getAcqCode());
        params.add(withdrawOrder.getCardNo());
        params.add(withdrawOrder.getAccountNo());
        params.add(withdrawOrder.getAccountName());
        params.add(withdrawOrder.getAmount());
        params.add(withdrawOrder.getFee());
        params.add(new Date());
        return baseDao.execute(sql, params.toArray());
    }

    @Override
    public int getSuccWithdrawCountByCardAndService(String cardNo, String service) throws Exception {
        String sql = " SELECT COUNT(id) AS countNum FROM t_withdraw_order WHERE card_no = ? AND last_update_time >= ? AND last_update_time <= ? AND service = ? AND status = ?";

        Date now = new Date();
        String currDateStr = DateUtil.format(now, "yyyy-MM-dd");

        List<Object> params = new ArrayList<>();
        params.add(cardNo);
        params.add(currDateStr + " 00:00:00");
        params.add(currDateStr + " 23:59:59");
        params.add(service);
        params.add(Constants.WITHDRAW_STATUS_SUCCESS);

        Map<String, Object> map = baseDao.findFirst(sql, params.toArray());

        if (null != map && !map.isEmpty()) {
            String countNum = StringUtil.filterNull(map.get("countNum"));
            try {
                if (StringUtils.isEmpty(countNum)) {
                    return 0;
                }
                return Integer.parseInt(countNum);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
        return 0;
    }

    /**
     * 回写统一出账表信息
     *
     * @param orderNo
     * @param newStatus
     * @param oldStatus
     * @param transferOrderNo
     * @param resCode
     * @param resMsg
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public int writeBackWithdrawInfo(String orderNo, String newStatus, String oldStatus, String transferOrderNo, String resCode, String resMsg) throws Exception {

        List<Object> params = new ArrayList<>();
        StringBuilder sb = new StringBuilder();
        sb.append(" UPDATE t_withdraw_order SET transfer_order_no = ?, status = ?, result_code = ?, result_msg = ? ");
        params.add(transferOrderNo);
        params.add(newStatus);
        params.add(resCode);
        params.add(resMsg);

        sb.append("  WHERE order_no = ?");
        params.add(orderNo);

        if (StringUtils.isNotBlank(oldStatus)) {
            sb.append(" AND status = ? ");
            params.add(oldStatus);
        }

        return baseDao.execute(sb.toString(), params.toArray());
    }

    /**
     * 修改统一出账通知次数
     *
     * @param orderNo
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public int updateWithdrawOrderNotifyNum(String orderNo) throws Exception {

        String sql = " UPDATE t_withdraw_order SET notify_num = notify_num + 1 WHERE order_no = ?";
        return baseDao.execute(sql, new Object[]{orderNo});
    }

    /**
     * 修改订单通知状态
     *
     * @param orderNo
     * @param notifyStatus
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public int updateWithdrawOrderNotifyStatus(String orderNo, String notifyStatus) throws Exception {

        String sql = " UPDATE t_withdraw_order SET is_need_notify = ? WHERE order_no = ? ";
        return baseDao.execute(sql, new Object[]{notifyStatus, orderNo});
    }

    /**
     * 查询需要30天内10分钟前创建的需要通知的统一出账记录
     *
     * @return
     * @throws Exception
     */
    @Override
    public List<WithdrawOrder> getNeedNotifyWithdrawOrder() throws Exception {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date now = new Date();

        Calendar nowCal = Calendar.getInstance();
        nowCal.setTime(now);
        nowCal.add(Calendar.DAY_OF_YEAR, -30);
        String beginTime = sdf.format(nowCal.getTime()) + " 00:00:00";

        nowCal = Calendar.getInstance();
        nowCal.setTime(now);
        nowCal.add(Calendar.MINUTE, -10);
        sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String endTime = sdf.format(nowCal.getTime());

        String sql = "SELECT * FROM t_withdraw_order WHERE status IN (?,?) AND is_need_notify = ? AND create_time >= ? AND create_time < ?";
        return baseDao.findList(WithdrawOrder.class, sql, new Object[]{Constants.WITHDRAW_STATUS_SUCCESS, Constants.WITHDRAW_STATUS_FAIL, Constants.IS_NEED_NOTIFY, beginTime, endTime});
    }

    /**
     * 根据卡片编号获取未知状态的交易
     *
     * @param cardNo
     * @return
     * @throws Exception
     */
    @Override
    public List<WithdrawOrder> getUnEndStatusWithdrawOrderByCardNo(String cardNo) throws Exception {

        String sql = "SELECT * FROM t_withdraw_order WHERE status IN (?) AND card_no = ? ";
        return baseDao.findList(WithdrawOrder.class, sql, new Object[]{Constants.WITHDRAW_STATUS_UNKNOW, cardNo});
    }

    /**
     * 获取30天内10分钟前创建的出账中状态的所有统一出账订单
     *
     * @return
     * @throws Exception
     */
    @Override
    public List<WithdrawOrder> getUnEndStatusWithdrawOrder() throws Exception {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date now = new Date();

        Calendar nowCal = Calendar.getInstance();
        nowCal.setTime(now);
        nowCal.add(Calendar.DAY_OF_YEAR, -30);
        String beginTime = sdf.format(nowCal.getTime()) + " 00:00:00";

        nowCal = Calendar.getInstance();
        nowCal.setTime(now);
        nowCal.add(Calendar.MINUTE, -5);
        sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String endTime = sdf.format(nowCal.getTime());

        String sql = " SELECT * FROM t_withdraw_order WHERE status IN (?) AND create_time >= ? AND create_time <= ? ";
        return baseDao.findList(WithdrawOrder.class, sql, new Object[]{Constants.ORDER_TRANS_STATUS_IN, beginTime, endTime});
    }

    @Override
    public WithdrawOrder getWithdrawOrderByService(String service, String serviceOrderNo) throws Exception {

        String sql = " SELECT * FROM t_withdraw_order WHERE service = ? AND service_order_no = ?";
        return baseDao.findFirst(WithdrawOrder.class, sql, new Object[]{service, serviceOrderNo});
    }

    /**
     * 获取商户已结算金额
     *
     * @param merType
     * @param merNo
     * @return
     * @throws Exception
     */
    @Override
    public String getSettledAmountByMer(String merType, String merNo) throws Exception {

        String sql = " SELECT IFNULL(SUM(amount), 0) AS amount FROM t_withdraw_order WHERE mer_type = ? AND mer_no = ? AND service = ? AND status = ? ";
        WithdrawOrder summaryOrder = baseDao.findFirst(WithdrawOrder.class, sql, new Object[]{merType, merNo, Constants.WITHDRAW_SERVICE_WITHDRAW, Constants.WITHDRAW_STATUS_SUCCESS});
        return summaryOrder == null ? "" : String.valueOf(summaryOrder.getAmount());
    }
}